package com.xq.sqlSession;

import com.xq.pojo.Configuration;
import com.xq.pojo.MappedStatement;
import com.xq.util.GenericTokenParser;
import com.xq.util.ParameterMapping;
import com.xq.util.ParameterMappingTokenHandler;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

public class SimpleExecutor extends BaseExecutor implements Executor{
    @Override
    public <E> List<E> findAll(Configuration configuration, MappedStatement mappedStatement, Object... params) throws Exception {
        //构建连接
        PreparedStatement preparedStatement = getPreparedStatement(configuration, mappedStatement, params);
        //sql执行获取返回值
        ResultSet resultSet = preparedStatement.executeQuery();
        //构建结果集盛放list
        List<Object> list = new ArrayList<>();
        //结果集解析
        //获取返回结果集对应的实体类
        String resultType = mappedStatement.getResultType();
        Class<?> resultClass = getClassType(resultType);
        while (resultSet.next()) {
            ResultSetMetaData metaData = resultSet.getMetaData();
            //构造实体
            Object newInstance = resultClass.newInstance();
            for (int i = 1; i <= metaData.getColumnCount(); i++) {
                String columnName = metaData.getColumnName(i);
                //获取列对应的值
                Object object = resultSet.getObject(columnName);
                //使用自省赋值
                PropertyDescriptor propertyDescriptor = new PropertyDescriptor(columnName, resultClass);
                Method writeMethod = propertyDescriptor.getWriteMethod();
                //第一个是要写入的实体，第二个参数是要写的值
                writeMethod.invoke(newInstance, object);
            }
            list.add(newInstance);
        }


        return (List<E>) list;
    }

    private Class<?> getClassType(String parameterType) throws Exception {
        if (parameterType != null) {
            Class<?> aClass = Class.forName(parameterType);
            return aClass;
        } else {
            return null;
        }
    }

    private BoundSql getBoundSql(String sql) {
        ParameterMappingTokenHandler parameterMappingTokenHandler = new ParameterMappingTokenHandler();
        GenericTokenParser genericTokenParser = new GenericTokenParser("#{","}",parameterMappingTokenHandler);
        String parseSql = genericTokenParser.parse(sql);
        List<ParameterMapping> parameterMappings = parameterMappingTokenHandler.getParameterMappings();

        return new BoundSql(parseSql,parameterMappings);
    }

    @Override
    public <T> T selectOne(Configuration configuration, MappedStatement mappedStatement, Object... params) {
        return null;
    }

    @Override
    public int doUpdate(Configuration configuration, MappedStatement mappedStatement, Object... params) throws Exception {
        PreparedStatement preparedStatement = getPreparedStatement(configuration, mappedStatement, params);
        int i = preparedStatement.executeUpdate();
        return i;
    }
}
